package com.ruoyi.system.service.impl;

import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.TreeSelectForArea;
import com.ruoyi.common.core.domain.entity.SysArea;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.system.mapper.SysAreaMapper;
import com.ruoyi.system.service.ISysAreaService;
import org.jxls.reader.ReaderBuilder;
import org.jxls.reader.XLSReadStatus;
import org.jxls.reader.XLSReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 部门管理 服务实现
 *
 * @author ruoyi
 */
@Service
public class SysAreaServiceImpl implements ISysAreaService {
    @Autowired
    private SysAreaMapper areaMapper;

    @Autowired
    private RedisCache redisCache;

    @Value(value = "${ruoyi.path}")
    public String basePath;
    @Value(value = "${ruoyi.templatePath}")
    public String templatePath;
    @Value(value = "${ruoyi.templateImport}")
    public String templateImport;
    /**
     * 查询部门管理数据
     *
     * @param dept 部门信息
     * @return 部门信息集合
     */
    @Override
//    @DataScope(deptAlias = "d")
    public List<SysArea> selectAreaList(SysArea dept) {
        return areaMapper.selectAreaList(dept);
    }

    @Override
    public List<SysArea> selectAreaListLazy(SysArea dept) {
        return areaMapper.selectAreaListLazy(dept);
    }

    @Override
    public List<SysArea> selectAreaTreeList(SysArea dept) {
        return areaMapper.selectAreaTreeList(dept);
    }

    /**
     * 构建前端所需要树结构
     *
     * @param depts 部门列表
     * @return 树结构列表
     */
    @Override
    public List<SysArea> buildAreaTree(List<SysArea> depts) {
        List<SysArea> returnList = new ArrayList<SysArea>();
        List<String> tempList = new ArrayList<String>();
        for (SysArea dept : depts) {
            tempList.add(dept.getDeptId());
        }
        for (Iterator<SysArea> iterator = depts.iterator(); iterator.hasNext(); ) {
            SysArea dept = (SysArea) iterator.next();
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(dept.getParentId())) {
                recursionFn(depts, dept);
                returnList.add(dept);
            }
        }
        if (returnList.isEmpty()) {
            returnList = depts;
        }
        return returnList;
    }

    /**
     * 构建前端所需要下拉树结构
     *
     * @param depts 部门列表
     * @return 下拉树结构列表
     */
    @Override
    public List<TreeSelectForArea> buildAreaTreeSelect(List<SysArea> depts) {
        List<SysArea> deptTrees = buildAreaTree(depts);
        return deptTrees.stream().map(TreeSelectForArea::new).collect(Collectors.toList());
    }

    @Override
    public List<SysArea> listAreabyParetnt(SysArea depts) {
        return areaMapper.listAreabyParetnt(depts);
    }
    /**
     * 根据角色ID查询部门树信息
     *
     * @param roleId 角色ID
     * @return 选中部门列表
     */
    @Override
    public List<Integer> selectAreaListByRoleId(String roleId) {
        //SysRole role = roleMapper.selectRoleById(roleId);
        return null;//areaMapper.selectAreaListByRoleId(roleId, role.isAreaCheckStrictly());
    }

    /**
     * 根据部门ID查询信息
     *
     * @param deptId 部门ID
     * @return 部门信息
     */
    @Override
    public SysArea selectAreaById(String deptId) {
        return areaMapper.selectAreaById(deptId);
    }

    @Override
    public SysArea selectAreaByIdInCatche(String areaId) {
        if (redisCache.hasKey(SysArea.CACHE_KEY_SYS_AREA_ID + "_" + areaId)) {
            return redisCache.getCacheObject(SysArea.CACHE_KEY_SYS_AREA_ID + "_" + areaId);
        }
        SysArea area = new SysArea();
        area = areaMapper.selectAreaById(areaId);
        if (area != null) {
            redisCache.setCacheObject(SysArea.CACHE_KEY_SYS_AREA_ID + "_" + area.getDeptId(), area);
        }
        return area;
    }

    /**
     * 根据ID查询所有子部门（正常状态）
     *
     * @param deptId 部门ID
     * @return 子部门数
     */
    @Override
    public int selectNormalChildrenAreaById(String deptId) {
        return areaMapper.selectNormalChildrenAreaById(deptId);
    }

    /**
     * 是否存在子节点
     *
     * @param deptId 部门ID
     * @return 结果
     */
    @Override
    public boolean hasChildByAreaId(String deptId) {
        int result = areaMapper.hasChildByAreaId(deptId);
        return result > 0 ? true : false;
    }

    /**
     * 查询部门是否存在用户
     *
     * @param deptId 部门ID
     * @return 结果 true 存在 false 不存在
     */
    @Override
    public boolean checkAreaExistUser(String deptId) {
        int result = areaMapper.checkAreaExistUser(deptId);
        return result > 0 ? true : false;
    }

    /**
     * 校验部门名称是否唯一
     *
     * @param dept 部门信息
     * @return 结果
     */
    @Override
    public String checkAreaNameUnique(SysArea dept) {
        String deptId = StringUtils.isNotBlank(dept.getDeptId()) ? dept.getDeptId() : "-1";
        SysArea info = areaMapper.checkAreaCodeUnique(dept.getCode(), dept.getParentId());
        if (StringUtils.isNotNull(info) && !deptId.equals(info.getDeptId())) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 新增保存部门信息
     *
     * @param dept 部门信息
     * @return 结果
     */
    @Override
    public int insertArea(SysArea dept) {
        clearCache();
        SysArea info = areaMapper.selectAreaById(dept.getParentId());
        // 如果父节点不为正常状态,则不允许新增子节点
        if (!UserConstants.DEPT_NORMAL.equals(info.getStatus())) {
            throw new CustomException("部门停用，不允许新增");
        }
        dept.setAncestors(info.getAncestors() + "," + dept.getParentId());
        return areaMapper.insertArea(dept);
    }

    /**
     * 修改保存部门信息
     *
     * @param dept 部门信息
     * @return 结果
     */
    @Override
    public int updateArea(SysArea dept) {
        clearCache();
        SysArea newParentArea = areaMapper.selectAreaById(dept.getParentId());
        SysArea oldArea = areaMapper.selectAreaById(dept.getDeptId());
        if (StringUtils.isNotNull(newParentArea) && StringUtils.isNotNull(oldArea)) {
            String newAncestors = newParentArea.getAncestors() + "," + newParentArea.getDeptId();
            String oldAncestors = oldArea.getAncestors();
            dept.setAncestors(newAncestors);
            updateAreaChildren(dept.getDeptId(), newAncestors, oldAncestors);
        }
        int result = areaMapper.updateArea(dept);
        if (UserConstants.DEPT_NORMAL.equals(dept.getStatus())) {
            // 如果该部门是启用状态，则启用该部门的所有上级部门
            updateParentAreaStatus(dept);
        }
        return result;
    }

    @Override
    @Transactional
    public int updateAreaSon(SysArea dept) {
        int i = updateArea(dept);

        SysArea where = new SysArea();
        where.setAncestors(dept.getDeptId() + "");
        List<SysArea> sysAreas = selectAreaList(where);
        for (SysArea area : sysAreas) {
            area.setDealtype(dept.getDealtype());
            area.setRiskflag(dept.getRiskflag());
            updateArea(area);
        }
        clearCache();
        return i;
    }

    /**
     * 修改该部门的父级部门状态
     *
     * @param dept 当前部门
     */
    private void updateParentAreaStatus(SysArea dept) {
        clearCache();
        String updateBy = dept.getUpdateBy();
        dept = areaMapper.selectAreaById(dept.getDeptId());
        dept.setUpdateBy(updateBy);
        areaMapper.updateAreaStatus(dept);
    }

    /**
     * 修改子元素关系
     *
     * @param deptId       被修改的部门ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    public void updateAreaChildren(String deptId, String newAncestors, String oldAncestors) {
        clearCache();
        List<SysArea> children = areaMapper.selectChildrenAreaById(deptId);
        for (SysArea child : children) {
            child.setAncestors(child.getAncestors().replace(oldAncestors, newAncestors));
        }
        if (children.size() > 0) {
            areaMapper.updateAreaChildren(children);
        }
    }

    /**
     * 删除部门管理信息
     *
     * @param deptId 部门ID
     * @return 结果
     */
    @Override
    public int deleteAreaById(String deptId) {
        return areaMapper.deleteAreaById(deptId);
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<SysArea> list, SysArea t) {
        // 得到子节点列表
        List<SysArea> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysArea tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<SysArea> getChildList(List<SysArea> list, SysArea t) {
        List<SysArea> tlist = new ArrayList<SysArea>();
        Iterator<SysArea> it = list.iterator();
        while (it.hasNext()) {
            SysArea n = (SysArea) it.next();
            if (StringUtils.isNotNull(n.getParentId()) && t.getDeptId().equals(n.getParentId())) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<SysArea> list, SysArea t) {
        return getChildList(list, t).size() > 0 ? true : false;
    }


    @Override
    @Transactional(readOnly = false)
    public void insertAreaFromCountryAllCode(int i) {
        SysArea areaParam = new SysArea();
        areaParam.setGrade((i - 1) + "");
        List<SysArea> areaList = areaMapper.selectAreaList(areaParam);
        List<SysArea> insertList = new ArrayList<>();
        for (SysArea area : areaList) {
            SysArea insertParam = new SysArea();
            insertParam.setGrade(i + "");
            insertParam.setRemarks(area.getRemarks());
            insertList.add(insertParam);
            if (insertList.size() > 100) {
                areaMapper.insertAreaFromCountryAllCodeBatch(insertList);
                insertList.clear();
            }
//            areaMapper.insertAreaFromCountryAllCode(insertParam);
        }
        if (!insertList.isEmpty()) {
            areaMapper.insertAreaFromCountryAllCodeBatch(insertList);
        }
    }


    @Override
    public List<SysArea> buildDeptTree(List<SysArea> depts) {
        List<SysArea> returnList = new ArrayList<SysArea>();
        List<String> tempList = new ArrayList<String>();
        for (SysArea dept : depts) {
            tempList.add(dept.getDeptId());
        }
        for (Iterator<SysArea> iterator = depts.iterator(); iterator.hasNext(); ) {
            SysArea dept = (SysArea) iterator.next();
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(dept.getParentId())) {
                recursionFn(depts, dept);
                returnList.add(dept);
            }
        }
        if (returnList.isEmpty()) {
            returnList = depts;
        }
        return returnList;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Map<String, Object> importInfo(SysArea depts, MultipartFile file) {
        String tmplName = "area.xml";
        //Resource resource = new ClassPathResource("templates/area.xml");
        clearCache();
        Map<String, Object> map = new HashMap<>();
        int i = 0;
        int index = 1;
        try {
            InputStream in = new FileInputStream(basePath + File.separator
                    + templatePath + File.separator + templateImport + File.separator + tmplName);
            XLSReader mainReader = ReaderBuilder.buildFromXML(in);
            //InputStream in = resource.getInputStream();
            //XLSReader mainReader = ReaderBuilder.buildFromXML(in);
            String errortext = "";
            List<SysArea> list = new ArrayList<>();
            Map beans = new HashMap();
            beans.put("list", list);
            XLSReadStatus readStatus = mainReader.read(file.getInputStream(), beans);
            if (readStatus.isStatusOK()) {
                for (SysArea sysArea : list) {
                    if (StringUtils.isNotBlank(sysArea.getIdx())) {
                        //TODO 字典翻译等未确认需求
                        // entity.setType(type);
                        SysArea entity = new SysArea();
                        /*entity.setDeptId(IdUtils.fastSimpleUUID());
                        BeanUtils.copyProperties(sysArea, entity, "id");*/
                        if (StringUtils.isNotBlank(sysArea.getProvinceName())) {
                            SysArea sheng = areaMapper.selectByCodeAndGrade(sysArea.getAncestors(), "3");
                            if (StringUtils.isNotBlank(sysArea.getCode())) {
                                SysArea shi = areaMapper.checkAreaCodeUnique(sysArea.getCode(), sheng.getDeptId());
                                if (shi != null) {
                                    sysArea.setDeptId(shi.getDeptId());
                                    sysArea.setParentId(sheng.getDeptId());
                                    this.updateArea(sysArea);
                                } else {
                                    sysArea.setParentId(sheng.getDeptId());
                                    this.insertArea(sysArea);
                                }
                            } else {
                                map.put("errorText", "序号为：" + sysArea.getIdx() + " 行，主数据与系统不匹配，请重新填写后导入!");
                                map.put("num", i);
                                return map;
                            }
                        }

                    } else {
                        map.put("num", "第" + index + "行数据，序号不能为空");
                        return map;
                    }
                }
            }
            // map.put("errorText","");
            map.put("num", "1");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    @Override
    public List<Map<String, Object>> selectdatajson(SysArea area) {
        return areaMapper.selectdatajson(area);
    }

    @Override
    public List<Map<String, Object>> selectdatajsonAll(SysArea area) {
        return areaMapper.selectdatajsonAll(area);
    }

    private void clearCache() {
        redisCache.deleteObject(SysArea.CACHE_KEY_SYS_AREA);
    }

    @Override
    public void updateReturnInfoRiskByArea() {
        areaMapper.updateReturnInfoRiskByArea();
    }

    @Override
    public AjaxResult updateSysAreaByJnfyRiskArea() {
        //将所有风险地区更新为疫情重点地区
        areaMapper.updateRiskLeavelToYQZD();
        //将所有中高风险县区更新为风险地区
        areaMapper.updateRiskLeavelToFXDQ();
        //将所有父节点为风险地区的地区更新为风险地区
        areaMapper.updateRiskLeavelToFXDQByPID();

        return AjaxResult.success("更新成功!");
    }

    @Override
    public boolean ifRiskArea(String reachedCity) {
        String[] citys = reachedCity.split(",");
        boolean risk = false;
        for (String city : citys) {
            if (redisCache.getCacheObject(SysArea.CACHE_KEY_SYS_AREA_PROVINCE_CITY + "_" + city) != null) {
                risk = true;
                break;
            }
            ;
        }
        return risk;
    }

    @Override
    public List<SysArea> selectRiskAreaByProvinceCity(String provinceCity) {
        return areaMapper.selectRiskAreaByProvinceCity(provinceCity);
    }



}
